package com.srtp.secureprotocol.cipherstream;


import com.srtp.secureprotocol.util.Util;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 填充输入流
 * 继承自FilterInputStream，在读取数据时自动添加填充字节
 *
 * 主要功能：
 * 1. 为原始数据流添加尾部填充
 * 2. 确保读取的数据长度符合加密算法的块大小要求
 * 3. 提供计算填充后数据长度的静态方法
 *
 * 使用场景：加密前对数据进行填充以满足块加密算法要求
 */
public class PaddingInputStream extends FilterInputStream {

    private long paddingRemaining;

    /**
     * 构造函数
     * @param inputStream 原始输入流
     * @param plaintextLength 原始数据长度（字节数）
     */
    public PaddingInputStream(InputStream inputStream, long plaintextLength) {
        super(inputStream);
        this.paddingRemaining = getPaddedSize(plaintextLength) - plaintextLength;
    }

    @Override
    public int read() throws IOException {
        int result = super.read();
        if (result != -1) return result;

        if (paddingRemaining > 0) {
            paddingRemaining--;
            return 0x00;
        }

        return -1;
    }

    @Override
    public int read(byte[] buffer, int offset, int length) throws IOException {
        int result = super.read(buffer, offset, length);
        if (result != -1) return result;

        if (paddingRemaining > 0) {
            length = Math.min(length, Util.toIntExact(paddingRemaining));
            paddingRemaining -= length;
            return length;
        }

        return -1;
    }

    @Override
    public int read(byte[] buffer) throws IOException {
        return read(buffer, 0, buffer.length);
    }

    @Override
    public int available() throws IOException {
        return super.available() + Util.toIntExact(paddingRemaining);
    }

    /**
     * 计算填充后的数据大小
     * 使用特定算法确保最小填充为541字节，并以1.05倍率增长
     *
     * @param size 原始数据大小
     * @return 填充后的数据大小
     */
    public static long getPaddedSize(long size) {
        return (int) Math.max(541, Math.floor(Math.pow(1.05, Math.ceil(Math.log(size) / Math.log(1.05)))));
    }
}

